//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using Microsoft.Research.ScientificWorkflow;

namespace Microsoft.Research.ScientificWorkflow.TridentModel
{
    #region Using Directives
    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Workflow.ComponentModel;
    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using SR = Microsoft.Research.DataLayer;
    #endregion

    [Serializable]
    public class SimpleBlackboxModel : BaseModel
    {
        #region Private Member Data
        /// <summary>
        /// Whether BuiltIn Model.
        /// </summary>
        private bool isBuiltIn;

        /// <summary>
        /// This is used to check if teh Activity Parameter Bindings are visible or not.
        /// </summary>
        private Visibility currentParameterBindingVisibility = Visibility.Visible;

        /// <summary>
        /// The execution status of the activity.
        /// </summary>
        private TridentActivityExecutionStatus currentTridentActivityExecutionStatus = TridentActivityExecutionStatus.None;
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="activity">
        /// The blackbox activity to be converted to blackbox model.
        /// </param>
        /// <param name="parentModel">
        /// The parent model.
        /// </param>
        public SimpleBlackboxModel(
            Activity activity,
            BaseCompositeModel parentModel)
        {
            if (activity != null)
            {
                this.GetDetailsFromActivity(activity, parentModel);
            }
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="activitySequence">
        /// Activity sequence which has to be converted to blackbox model.
        /// </param>
        /// <param name="parentModel">
        /// The parent model.
        /// </param>
        public SimpleBlackboxModel(
            SR.ActivitySequence activitySequence,
            BaseCompositeModel parentModel)
        {
            if (activitySequence != null)
            {
                this.GetDetailsFromActivity(activitySequence.Activity, parentModel, activitySequence.Name);
            }
        }

        public SimpleBlackboxModel(
            SR.Activity erActivity,
            BaseCompositeModel parentActivityModel,
            string uniqueId)
        {
            if (erActivity != null)
            {
                this.GetDetailsFromActivity(erActivity, parentActivityModel, uniqueId);
            }
        }

        #endregion

        #region Properties
        /// <summary>
        /// Gets or sets the visibility of the Bindings.
        /// </summary>
        public override System.Windows.Visibility CurrentParameterBindingVisibility
        {
            get
            {
                return this.currentParameterBindingVisibility;
            }
            set
            {
                this.currentParameterBindingVisibility = value;
            }
        }

        /// <summary>
        /// Gets whether the Activity is of Built In Type.
        /// </summary>
        public bool IsBuiltIn
        {
            get
            {
                return this.isBuiltIn;
            }
        }

        /// <summary>
        /// Gets and sets the CurrentActivityExecutionStatus.
        /// </summary>
        public TridentActivityExecutionStatus CurrentTridentActivityExecutionStatus
        {
            get
            {
                return this.currentTridentActivityExecutionStatus;
            }

            set
            {
                if (value != this.currentTridentActivityExecutionStatus)
                {
                    this.currentTridentActivityExecutionStatus = value;
                    this.RaisePropertyChanged("CurrentTridentActivityExecutionStatus");
                }
            }
        }

        /// <summary>
        /// A flag to check if the model is a simple activity model.
        /// </summary>
        public override bool IsSimpleActivityModel
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// A flag to check if the model is a composite activity model.
        /// </summary>
        public override bool IsCompositeActivityModel
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// A flag to check if the model is a subsection model.
        /// </summary>
        public override bool IsSubsectionModel
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// A flag to check if the model is a foractivitymodel.
        /// </summary>
        public override bool IsForActivityModel
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// A flag to check if the model is a replicatoractivitymodel.
        /// </summary>
        public override bool IsReplicatorActivityModel
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// A flag to check if the model is a ifelseactivitymodel.
        /// </summary>
        public override bool IsIfElseActivityModel
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// A flag to check if the model is a simpleblackboxmodel.
        /// </summary>
        public override bool IsSimpleBlackBoxModel
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// A flag to check if the model is a compositeblackboxmodel.
        /// </summary>
        public override bool IsCompositeBlackBoxModel
        {
            get
            {
                return false;
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Using the BaseVisitor, perform the operation.
        /// </summary>
        /// <param name="visitor">
        /// The implementation of visitor.
        /// </param>
        public override void Accept(TridentBaseVisitor visitor)
        {
            visitor.VisitSimpleBlackboxModel(this);
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Initialze the activity model, recursively, using the Activity object.
        /// </summary>
        /// <param name="activity">
        /// ComponentModel.Activity object.
        /// </param>
        /// <param name="parentActivityModel">
        /// The parent activity model.
        /// </param>
        private void GetDetailsFromActivity(
            Activity activity,
            BaseCompositeModel parentActivityModel)
        {
            Type activityType = activity.GetType();
            this.UniqueId = activity.Name;
            this.ActivityClass = activityType.FullName;
            this.Id = Guid.Empty;

            // Get the label details from the attribute.
            object[] attsNameLabel = null;
            try
            {
                attsNameLabel = activityType.GetCustomAttributes(typeof(NameAttribute), false);
            }
            catch (TypeLoadException ex)
            {
                Logger.Write(ex.Message);
            }

            this.Name = activityType.Name;

            if ((attsNameLabel == null) || ((attsNameLabel != null) && (attsNameLabel.Length == 0)))
            {
                this.Label = activityType.Name;
            }
            else
            {
                this.Label = ((NameAttribute)attsNameLabel[0]).Label;
            }

            // Get the description details from the attribute.
            object[] attsDesc = null;
            try
            {
                attsDesc = activityType.GetCustomAttributes(typeof(DescriptionAttribute), false);
            }
            catch (TypeLoadException ex)
            {
                Logger.Write(ex.Message);
            }

            if (attsDesc != null && attsDesc.Length > 0)
            {
                this.Description = ((DescriptionAttribute)attsDesc[0]).Description;
            }

            this.IsDeleted = false;

            if (parentActivityModel != null)
            {
                this.ParentModel = parentActivityModel;
            }

            if (activityType.Namespace.Equals("System.Workflow.Activities") || activityType.Namespace.Equals("System.Workflow.ComponentModel"))
            {
                this.isBuiltIn = true;
            }
            else
            {
                this.isBuiltIn = false;
            }
        }

        /// <summary>
        /// Initialze the activity model, recursively, using the Activity Sequence.
        /// </summary>
        /// <param name="activitySequence">
        /// Activity sequence which has to be converted to blackbox model.
        /// </param>
        /// <param name="parentModel">
        /// The parent model.
        /// </param>
        private void GetDetailsFromActivity(
            SR.Activity erActivity, 
            BaseCompositeModel parentActivityModel, 
            string uniqueName)
        {
            this.ActivityClass = erActivity.ActivityClass;

            this.UniqueId = uniqueName;

            this.Id = ((SR.IObject)erActivity).ID;

            this.Name = erActivity.Name;

            this.Label = erActivity.Label;

            this.Description = erActivity.Description;

            this.IsDeleted = erActivity.IsDeleted;

            this.isBuiltIn = erActivity.IsBuiltIn;

            this.PopulateAssociatedAssemblies(erActivity);

            if (parentActivityModel != null)
            {
                this.ParentModel = parentActivityModel;
            }
        }
        #endregion
    }
}
